package com.functest.orm
//import com.micex.forts.autotests.beans.sessions.OperationResultMessage
import com.functest.util.CodeBased
import com.functest.framework.BaseFunctionalTest
import org.testng.annotations.DataProvider
import org.testng.annotations.Test

class MapperTest extends BaseFunctionalTest {
    enum Codez implements CodeBased {
        OK(0), SOMETHING_TERRIBLE(20);

        final int code;

        Codez(code) {
            this.code = code
        }

        static Codez fromCode(int code) {
            try {
                values ().grep { it.code == code }.last ()
            } catch (NoSuchElementException e) {
                throw new UnsupportedOperationException ("Unsupported code:${code} (Exception was ${e})")
            }
        }
    }

    static enum YesNo {
        Y, N
    }

    static class UsesYesNo {
        def boolOption
        def enabled
    }

    @Test
    void stringEnumTest() {
        asTest {
            Mapper ohYesMapper = new Mapper (new MapperFields ().with {
                field ('boolOption')
                field ('enabled', 'enabled', com.functest.orm.MapperUtil.transform.stringEnum (YesNo), com.functest.orm.MapperUtil.transformBack.stringEnum (YesNo))
                delegate as MapperFields
            })
            Map res = [:]

            asStep ('trasnformMap') {
                res = ohYesMapper.transformMap ([boolOption: 'ZeOption', enabled: 'Y'])

                assert res.enabled == YesNo.Y
                assert res.enabled instanceof YesNo
                assert res == [boolOption: 'ZeOption', enabled: YesNo.Y]
            }
            asStep ('mapBack') {
                assert ohYesMapper.mapBack (res) == [boolOption: 'ZeOption', enabled: 'Y']
            }

            asStep ('fieldValues') {
                assert ohYesMapper.getMappedFieldValues (new UsesYesNo (boolOption: false,
                        enabled: YesNo.Y)) == [boolOption: false, enabled: YesNo.Y]
            }
        }

    }

//    @Test
//    void positiveDefaultTransformationsTest() {
//        asTest () {
//            asStep {
//                Mapper messageMapper = new Mapper (new MapperFields ().with {
//                    field ('code', 'retCode')
//                    field (new Field (name: 'description', from: ['msg', 'detail'],
//                            transform:
//                                    { Field f, Map map -> "${map['msg']}|${map['detail']}" },
//                            transformBack:
//                                    { Field f, def value ->
//                                        List elements = (value as String).split ('\\|')
//                                        [msg: elements[0], detail: elements[1]] as Map
//                                    }
//                    ))
//                    delegate as MapperFields
//                })
//
//                def source = [retCode: 20, msg: 'A Message', detail: 'Blah-blah']
//                OperationResultMessage res = OperationResultMessage.fromResult (messageMapper, source)
//                println res;
//                assert messageMapper.mapBack (res) == source
//
//            }
//
//            asStep {
//                Mapper messageMapper = new Mapper (new MapperFields().with {
//                    field ('RetCode', ['RetCode'], com.funktest.orm.MapperUtil.transform.codeBasedEnum (Codez), com.funktest.orm.MapperUtil.transformBack.codeBasedEnum (Codez))
//                    field ('RetText')
//                    delegate as MapperFields
//                })
//
//                def source = [RetCode: 20, RetText: 'Ouch!']
//
//                Map rez = messageMapper.transformMap (source)
//                assert messageMapper.mapBack (rez) == source
//            }
//        }
//    }




    class SimpleClass {
        int key
        int second
    }

    @DataProvider
    Object[][] mapBackTestData(){
        Mapper mapper = new Mapper(new MapperFields().with {
            field('key')
            field('second', 'key')
            delegate as MapperFields
        })

        int value = 193891
        Map map = [key: value, _key:value]

        Map columnAliases = [:]
        columnAliases.put('key','_key')

        Class resClass = SimpleClass

        return [[mapper, map, columnAliases, resClass]]
    }

    @Test(dataProvider = 'mapBackTestData')
    def <T> void mapBackTest(Mapper mapper, Map map, Map columnAliases, Class<T> resClass){
        asTest {
            asStep("mapBackTest"){
                Map transformedMap = mapper.transformMap(map, columnAliases)
                T res = mapper.buildFromTranformed(transformedMap, resClass)
                Map mapBack = mapper.mapBack(res, columnAliases)
                com.functest.framework.Assertions.weakAssertSilently("sizes of map and transformed back map doesn't matches", mapBack.size() == map.size())
                map.keySet().each { String key ->
                    Object value = map.get(key)
                    Object backValue = mapBack.get(key)
                    com.functest.framework.Assertions.weakAssertSilently("weak assert failed:\n" +
                            "field: $key\n" +
                            "value: $value\n" +
                            "back transform value: $backValue", value == backValue)
                }
            }
        }
    }

    @DataProvider
    Object[][] constructorDataProvider(){

        MapperFields builder = new MapperFields().with {
            field('key')
            field('first')
            delegate as MapperFields
        }
        Mapper m = new Mapper(builder)

        return [[m]]
    }

    @Test(dataProvider = 'constructorDataProvider')
    void constructorTest(Mapper m){
        asTest {
            Mapper mapper = new Mapper(m)
            asStep('builder test'){
                assert mapper.allFields ==  m.allFields
            }
            asStep('keyField test'){
                assert mapper.keyField == m.keyField
            }
        }
    }

}
